<style scoped>
  .box {
    width: 500px;
    height: 500px;
    border: 1px solid #ccc;
    position: relative;
  }
  .cart {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 50px;
    height: 50px;
  }
  .ball {
    width: 20px;
    height: 20px;
    background: red;
    border-radius: 50%;
  }
</style>


<template>
  <div>
      <div class="box">
        <button @click="isShow=!isShow">+</button>
        <transition
          v-on:before-enter="beforeEnter"
          v-on:enter="enter"
          v-on:after-enter="afterEnter">
          <div class="ball" v-show="isShow"></div>
        </transition>
        

        <img class="cart" src="https://img1.baidu.com/it/u=3761831681,4005524739&fm=253&fmt=auto&app=138&f=PNG?w=500&h=500" alt="">
      </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data () {
    return {
      isShow: false,
    }
  },
  methods: {
    // 进入动画开始前调用
    beforeEnter: function (el) {
      // ...
      console.log('beforeEnter')
      // 让小球回到初始位置
       el.style.transform = 'translate(0, 0)'
    },
    
    /* 
    进入动画开始时调用
    在此给el添加过渡相关的样式
    */
    enter: function (el, done) {
      console.log('enter')

      el.offsetLeft // 只要执行触发重排代码, 过渡才会有效果 读取一属性也会触发重排

      el.style.transition = 'all .5s'
      el.style.transform = 'translate(450px, 430px)' 
      
      done()  // 标识动画完成, 触发afterEnter调用
    },
    // 进入动画结束时调用
    afterEnter: function (el) {
      console.log('afterEnter')
      // 隐藏小球
      this.isShow = false
    },
  }
}
</script>

